package ch.connection;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
//import java.util.HashMap;
import javax.net.ServerSocketFactory;

/** Classe per la gestione del server POP
 * 
 * @author Giovanni Franza - GPLv3 - 8/6/2011
 *
 */

public class POP extends Thread {

	private StateManager sm;
	private User user = new User();
	private Pass pass = new Pass();
	private Stat stat = new Stat();
	private List list = new List();
	private Uidl uidl = new Uidl();
	private Retr retr = new Retr();
	private Dele dele = new Dele();

	/** Construttore - setta la macchina a stati.
	 *
	 */

	public POP() {		
		sm = new StateManager( "+OK Welcome to javapopserver\n", "250 2.0.0 Ok: queued\n", ' '  );
		sm.add( new Action( StateManager.SAME, "capa", null,  "+OK Capability list follows\nUSER\n.\n", "-ERR [NOT FOUND]\n", StateManager.SAME ) );
		sm.add( new Action( StateManager.SAME, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
		sm.add( new Action( StateManager.SAME, "auth", null,  "+OK Supported SASL mechanisms:\nX-NONE\n.\n", "-ERR [NOT FOUND]\n", StateManager.SAME ) );
		sm.add( new Action( StateManager.SAME, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
		sm.add( new Action( StateManager.SAME, "user", user,  "+OK pass required\n", "-ERR [NOT FOUND]\n", StateManager.CHANGE ) );
		sm.add( new Action( StateManager.SAME, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
		sm.add( new Action( StateManager.CHANGE, "pass", pass,  "+OK\n", "-ERR [AUTH]\n", StateManager.CHANGE ) );
		sm.add( new Action( StateManager.SAME, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
		sm.add( new Action( StateManager.CHANGE, "stat", stat,  "+OK\n", "-ERR [NOT FOUND]\n", StateManager.CHANGE ) );
		sm.add( new Action( StateManager.SAME, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
		sm.add( new Action( StateManager.CHANGE, "list", list,  "+OK\n", "-ERR\n", StateManager.CHANGE ) );
		sm.add( new Action( StateManager.SAME, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
		sm.add( new Action( StateManager.CHANGE, "uidl", uidl,  "+OK\n.\n", "-ERR\n", StateManager.CHANGE ) );
		sm.add( new Action( StateManager.SAME, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
		sm.add( new Action( StateManager.CHANGE, "retr", retr,  "+OK\n", "-ERR\n", StateManager.SAME ) );
		sm.add( new Action( StateManager.SAME, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
		sm.add( new Action( StateManager.SAME, "dele", dele,  "+OK\n", "-ERR\n", StateManager.SAME ) );
		sm.add( new Action( StateManager.CHANGE, "quit", null,  "+OK Pop server signing off\n", "+OK Pop server signing off\n", StateManager.ABORT ) );
	}

	/** getter della macchina a stati.
	 *
	 */

	public StateManager getStateManager( ) {
		return sm;
	}

	/** Il run fa tutto il lavoro.
	 *
	 */
	
	public void run() {
		try {
			System.out.println( "Welcome to the stupid, quick and dirty POP server" ); 
			System.out.println( "Licenced as per GPLv3 by HB9EIK - Giovanni" ); 
			// unprivileged port to be able to launch as not root
		    int port = 1110;
		    // SMTP server creation
		    ServerSocketFactory socketFactory = ServerSocketFactory.getDefault();
			ServerSocket ssocket = socketFactory.createServerSocket(port);
			// Serving requests (serialized) 
			for( ;; ) {
			    // Listen for connections
			    Socket socket = ssocket.accept();	
			    // Handle connections
			    POPWorker sslworker = new POPWorker( socket, this );
			    sslworker.start();
			}
		} catch(IOException e) {
			System.out.println(e);
		}
	}

}
